﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace ExeIconGetter_cs_x64 {

    public class IconGetter {

        public string GetIconBytes(string inputPath, int xsize, int ysize) {
            //选中文件中的图标总数
            var iconTotalCount = PrivateExtractIcons(inputPath, 0, 0, 0, null, null, 0, 0);
            //用于接收获取到的图标指针
            IntPtr[] hIcons = new IntPtr[iconTotalCount];
            //对应的图标id
            int[] ids = new int[iconTotalCount];
            //成功获取到的图标个数
            var successCount = PrivateExtractIcons(inputPath, 0, xsize, ysize, hIcons, ids, iconTotalCount, 0);
            //
            List<string> imageData = new List<string>();
            //遍历并保存图标
            for (var i = 0; i < successCount; i++) {
                //指针为空，跳过
                if (hIcons[i] == IntPtr.Zero) {
                    continue;
                }
                using (var ico = Icon.FromHandle(hIcons[i])) {
                    using (var myIcon = ico.ToBitmap()) {
                        MemoryStream ms = new MemoryStream();
                        myIcon.Save(ms, ImageFormat.Png);
                        byte[] b = ms.ToArray();
                        StringBuilder byteSb = new StringBuilder();
                        for (int j = 0; j < b.Length; j++) {
                            byteSb.Append(b[j]);
                            byteSb.Append(".");
                        }
                        imageData.Add(byteSb.ToString());
                    }
                }
                //内存回收
                DestroyIcon(hIcons[i]);
            }
            StringBuilder strSb = new StringBuilder();
            foreach (string data in imageData) {
                strSb.Append(data.Substring(0, data.Length - 1));
                strSb.Append(",");
            }
            string result = strSb.ToString();
            return result.Substring(0, result.Length - 1);
        }

        [DllImport("User32.dll")]
        public static extern int PrivateExtractIcons(
            string lpszFile, //file name
            int nIconIndex,  //The zero-based index of the first icon to extract.
            int cxIcon,      //The horizontal icon size wanted.
            int cyIcon,      //The vertical icon size wanted.
            IntPtr[] phicon, //(out) A pointer to the returned array of icon handles.
            int[] piconid,   //(out) A pointer to a returned resource identifier.
            int nIcons,      //The number of icons to extract from the file. Only valid when *.exe and *.dll
            int flags        //Specifies flags that control this function.
        );

        //details:https://msdn.microsoft.com/en-us/library/windows/desktop/ms648063(v=vs.85).aspx
        //Destroys an icon and frees any memory the icon occupied.
        [DllImport("User32.dll")]
        public static extern bool DestroyIcon(
            IntPtr hIcon //A handle to the icon to be destroyed. The icon must not be in use.
        );

    }

}
